/*
 * ComponenteDistribuidorGenerador.java
 *
 * Copyright 2011 Universidad Francisco de Paula Santander (UFPS).
 * Todos los Derechos Reservados.
 * Creado el 15/03/2011, 06:00:05 PM
 */

package com.ufps.cuatro.modelo.representacion.componente;

import com.ufps.cuatro.modelo.representacion.ConvertirComponenteDistribuidor;
import com.ufps.cuatro.modelo.representacion.ObjetoTipoDatoReflexion;
import com.ufps.cuatro.util.TipoCaso;
import com.ufps.cuatro.util.Utileria;
import com.ufps.cuatro.util.base.ComponenteBaseStandar;
import com.ufps.cuatro.util.generadores.codeobject.CodeContextLine;
import com.ufps.cuatro.util.generadores.codeobject.CodeContextMethod;
import com.ufps.cuatro.util.generadores.codeobject.EnumContextMethod;
import java.util.ArrayList;

/**
 * <i><b>ComponenteDistribuidorGenerador:</b></i><p>Esta Clase abstracta es la Base de los Componentes
 * Generadores y su Finalidad es Representar Elementos del Modelo Analizado que
 * generarán una vista o fragmento de una Interfaz Gráfica.</p><p> Un Elemento del Modelo 
 * Analizado puede ser: un Atributo (<code>Field</code>), un Método (<code>Method</code>), 
 * un Parametro (<code>Class<?></code>) ó incluso una Clase (<code>Class<?></code>).</p> 
 * 
 * La Clase incluye propiedades generales y metodos que sus subtipos desarrollarán
 * especificamente de acuerdo a su rol.
 * 
 * @author Carlos A. Torres C. - Dolly E. Guerrero. <https://code.google.com/p/tesis4dor/>
 * @version 1.0 15/03/2011
 * @see ComponenteDistribuidor
 * @see ObjectBase
 */
public abstract class ComponenteDistribuidorGenerador extends ComponenteDistribuidor implements ConvertirComponenteDistribuidor{
    private static final long serialVersionUID = -3742960206061518640L;
    
    /**
     * Serie Númerica para la generación de id de Objetos.
     */
    public static int serialIdComponenteGenerador;            
    private int idClaseComponenteGenerador;  
    /**
     * Tipo de Dato que Representa el Componente.
     */
    protected ObjetoTipoDatoReflexion objTipoDato;  
    /**
     * ClassPath del Tipo de Dato que Representa el Componente.
     */
    protected String strClassPathTipoDato;        
    /**
     * Simple Name del ClassPath del Tipo de Dato que Representa el Componente.
     */
    protected String strSimpleClassPathTipoDato;
    /**
     * Determina si el <code>ComponenteDistribuidorGenerador</code> será generado como
     * una interfaz gráfica independientemente.     
     */
    protected boolean independiente = false;
    /**
     * Indica los Casos Compatibles para los cuales la representación puede aplicar.
     */
    protected ArrayList<TipoCaso> objCasosCompatibles;
    /**
     * Determina el Caso de Represetnación para el Tipo de Dato del Modelo Analizado.
     */
    protected TipoCaso eCaso; 
    /**
     * Determina si se utilizara el ComponenteBeans Genérico para la Representación
     * del Tipo de Dato.
     */
    protected boolean generarEncapsulacionBeans = false;
    /**
     * Componente Padre que contiene el Método Representado por el Componente
     * actual.
     */
    protected ComponenteDistribuidorGeneradorClaseCompleja objComponenteParent;
    protected String strLabelName;
    protected String strLabelTitle;
    protected boolean auto = false;

    /**
     * Constructor utilizado en la Implementación.
     * @param objComponenteBase Componente Base que contiene la Información necesaria para crear el Control Swing
     * que representará el <code>Componente</code>.
     * @param strClassPathTipoDato      
     * @param heredado @DefinicionParametro
     * @param previsualizar   @DefinicionParametro
     */
    public ComponenteDistribuidorGenerador(ComponenteBaseStandar objComponenteBase, String strClassPathTipoDato, boolean heredado, boolean previsualizar) {
        super(objComponenteBase, true, true);
        this.strClassPathTipoDato = strClassPathTipoDato;
        this.heredado = heredado;
        this.previsualizar = previsualizar;
        this.objCasosCompatibles = new ArrayList<TipoCaso>();
        this.dni = Utileria.leerRecursoTexto("Utileria.dni.componente.distribuidor.generador");   
        if(!heredado) {
            this.idClaseComponenteGenerador = (!previsualizar) ?
                    ComponenteDistribuidorGenerador.serialIdComponenteGenerador++ :
                    ComponenteDistribuidorGenerador.serialIdComponenteGenerador;
        }        
    }    

    /**
     * Devuelve el id de creación del Componente Generador. 
     * @return id de creación del Componente.
     */
    public int getIdClaseComponenteGenerador() {
        return idClaseComponenteGenerador;
    }         
    
    /**
     * Devuelve el Tipo de Dato que representa el Componente.
     * @return Tipo de Dato que representa el Componente.
     */
    public ObjetoTipoDatoReflexion getObjTipoDato() {
        return objTipoDato;
    }

    /**
     * Establece el Tipo de Dato que representa el Componente.
     * @param objTipoDato Tipo de Dato que representa el Componente.
     */
    public void setObjTipoDato(ObjetoTipoDatoReflexion objTipoDato) {
        this.objTipoDato = objTipoDato;
    }
    
    /**
     * Devuelve el ClassPath del Tipo de Dato Representado.
     * @return ClassPath del Tipo de Dato Representado.
     */
    public String getStrClassPathTipoDato() {
        return strClassPathTipoDato;
    }
    
    /**
     * Devuelve el Simple Name del ClassPath del Tipo de Dato Representado.
     * @return Simple Name del ClassPath del Tipo de Dato Representado.
     */
    public String getStrSimpleClassPathTipoDato() {
        return strSimpleClassPathTipoDato;
    }

    /**
     * Establece el Simple Name del ClassPath del Tipo de Dato Representado.
     * @param strSimpleClassPathTipoDato 
     */
    public void setStrSimpleClassPathTipoDato(String strSimpleClassPathTipoDato) {
        this.strSimpleClassPathTipoDato = strSimpleClassPathTipoDato;
    }    

    /**
     * Establece el ClassPath del Tipo de Dato Representado.
     * @param strClassPathTipoDato ClassPath del Tipo de Dato Representado.
     */
    public void setStrClassPathTipoDato(String strClassPathTipoDato) {
        this.strClassPathTipoDato = strClassPathTipoDato;
    }
    
    /**
     * Devuelve la Colección de Casos Compatibles para los cuales la representación puede aplicar.
     * @return @DefinicionReturn
     */
    public ArrayList<TipoCaso> getObjCasosCompatibles() {
        return objCasosCompatibles;
    }

    /**
     * Establece la Colección de Casos Compatibles para los cuales la representación puede aplicar.
     * @param objCasosCompatibles Colección de Casos Compatibles para los cuales la representación puede aplicar.
     */
    public void setObjCasosCompatibles(ArrayList<TipoCaso> objCasosCompatibles) {
        this.objCasosCompatibles = objCasosCompatibles;
    }
    
    /**
     * Devuelve el Tipo de Caso de Representación del Tipo de Dato Representado.
     * @return Tipo de Caso de Representación del Tipo de Dato Representado.
     */
    public TipoCaso geteCaso() {
        return eCaso;
    }

    /**
     * Establece el Tipo de Caso de Representación del Tipo de Dato Representado.
     * @param eCaso Tipo de Caso de Representación del Tipo de Dato Representado.
     */
    public void seteCaso(TipoCaso eCaso) {
        this.eCaso = eCaso;
    }   

    @Override
    public void ok() {
        if(this.previsualizar){
            this.idClaseComponenteGenerador = ComponenteDistribuidorGenerador.serialIdComponenteGenerador++;
            this.previsualizar = false;
        }
    } 
    @Override
     public int compareTo(Object o) {
        ComponenteDistribuidorGenerador obj = (ComponenteDistribuidorGenerador) o;
        if(this.idClaseComponenteGenerador > obj.idClaseComponenteGenerador) {
            return 1;
        }
        else if(this.idClaseComponenteGenerador < obj.idClaseComponenteGenerador) {
            return -1;
        }
        else {
            return 0;
        }
    }
    
    

//    @Override
//    protected Object clone() {
//        ComponenteDistribuidorGenerador objClon = null;
//        //Primero se Clona la Referencia Local
//        objClon = (ComponenteDistribuidorGenerador) super.clone();
//        //Ahora se hace la Clonación Profunda
//        if(objTipoDato != null){
//            ((ComponenteDistribuidorGenerador)objClon).setObjTipoDato(objTipoDato);
//        }
//        if(strClassPathTipoDato != null){
//            ((ComponenteDistribuidorGenerador)objClon).setStrClassPathTipoDato(strClassPathTipoDato);
//        }
//        if(strSimpleClassPathTipoDato != null){
//            ((ComponenteDistribuidorGenerador)objClon).setStrSimpleClassPathTipoDato(strSimpleClassPathTipoDato);
//        }
//        return objClon;
//    }

    public boolean isGenerarEncapsulacionBeans() {
        return generarEncapsulacionBeans;
    }

    public void setGenerarEncapsulacionBeans(boolean generarEncapsulacionBeans) {
        this.generarEncapsulacionBeans = generarEncapsulacionBeans;
    }

    public boolean isIndependiente() {
        return independiente;
    }

    public void setIndependiente(boolean independiente) {
        this.independiente = independiente;
    }
    
    /**
     * Devuelve el Componente Padre que contiene el Método Representado por el Componente
     * actual.
     * @return Componente Padre que contiene el Método Representado por el Componente
     * actual.
     */
    public ComponenteDistribuidorGeneradorClaseCompleja getObjComponenteParent() {
        return objComponenteParent;
    }

    /**
     * Establece el Componente Padre que contiene el Método Representado por el Componente
     * actual.
     * @param objComponenteParent Componente Padre que contiene el Método Representado por el Componente
     * actual.
     */
    public void setObjComponenteParent(ComponenteDistribuidorGeneradorClaseCompleja objComponenteParent) {
        this.objComponenteParent = objComponenteParent;
    }

    public String getStrLabelName() {
        return strLabelName;
    }

    public void setStrLabelName(String strLabelName) {
        this.strLabelName = strLabelName;
    }

    public String getStrLabelTitle() {
        return strLabelTitle;
    }

    public void setStrLabelTitle(String strLabelTitle) {
        this.strLabelTitle = strLabelTitle;
    }

    public boolean isAuto() {
        return auto;
    }

    public void setAuto(boolean auto) {
        this.auto = auto;
    }
    
    public CodeContextMethod generateSourceCodeSyntaxEncapsulatedFunction() {        
        String strNombreTipoDato;
        if(objTipoDato.getObjCaso().geteCaso() == TipoCaso.ePrimitivo){
            strNombreTipoDato = objTipoDato.getStrClassPath();
        }
        else{
            strNombreTipoDato = objTipoDato.getObjClass().getSimpleName();
        }            
        strNombreTipoDato = Utileria.getKamelCaseCapital(strNombreTipoDato);

        CodeContextMethod objCodeContextMethod = new CodeContextMethod();
        objCodeContextMethod.seteContextMethod(EnumContextMethod.eSet);

        String strLine = objTipoDato.getStrClassPath() + " getVal" + strNombreTipoDato + getName();
        CodeContextLine objCodeContextLine = new CodeContextLine(strLine);
        objCodeContextMethod.setObjDefinition(objCodeContextLine);
        strLine = "throw new UnsupportedOperationException(\"Implementación Generica.\");";
        objCodeContextLine = new CodeContextLine(strLine);
        objCodeContextMethod.getObjLines().add(objCodeContextLine);
        return objCodeContextMethod;
    }
}
